package com.uobgroup.ews.uam.core.dao.ldap;

import java.util.List;

import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.AttributesMapperCallbackHandler;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.stereotype.Repository;

import com.uobgroup.ews.uam.core.configuration.AppConfig;
import com.uobgroup.ews.uam.core.model.Person;

@Repository("adDao")
public class ADDaoImpl implements ADDao {

  public static final String LDAP_DN_PERSON = "ldap_ad_dn_person";
  // public static final String LDAP_DN_PERSON = "cn=p8admin,cn=users,dc=uobdev,dc=smsmt,dc=com";
   
   public static final String LDAP_FILTER_PERSON = "ldap_ad_filter_person";

   public static final String LDAP_ATTRIBUTE_FIRSTNAME = "ldap_ad_attr_firstname";

   public static final String LDAP_ATTRIBUTE_LASTNAME = "ldap_ad_attr_lastname";

   public static final String LDAP_ATTRIBUTE_EMAIL = "ldap_ad_attr_email";

   public static final String LDAP_ATTRIBUTE_ACCOUNTNAME = "ldap_ad_attr_accountname";

   public static final String LDAP_ATTRIBUTE_COUNTRY = "ldap_ad_attr_country";

   public static final String LDAP_ATTRIBUTE_SID = "ldap_ad_attr_sid";

   private LdapTemplate adLdapTemplate;

   @Autowired
   public ADDaoImpl(@Qualifier("adLdapTemplate") LdapTemplate adLdapTemplate) {
      this.adLdapTemplate = adLdapTemplate;
   }

   @Override
   @SuppressWarnings("unchecked")
   public Person findUser(String username) {
      AppConfig.validate(LDAP_DN_PERSON);
      String baseDN = AppConfig.getProperty(LDAP_DN_PERSON);
      String filter = AppConfig.getProperty(LDAP_FILTER_PERSON);

      ADPersonAttributesMapper mapper = new ADPersonAttributesMapper();
      AttributesMapperCallbackHandler handler = new AttributesMapperCallbackHandler(mapper);

      CustomSearchExecutor searchExecutor = new CustomSearchExecutor();
      searchExecutor.setBaseDN(baseDN);
      searchExecutor.setFilter(filter);
      searchExecutor.setParas(new String[] { username });

      adLdapTemplate.search(searchExecutor, handler);
      List<Person> result = handler.getList();
      if (result.isEmpty()) {
         return null;
      }
      return result.get(0);
   }

   private class ADPersonAttributesMapper implements AttributesMapper {

      public Person mapFromAttributes(Attributes attributes) throws NamingException {
         Person person = new Person();
         Attribute attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_FIRSTNAME));
         person.setFirstName(attValue == null ? null : attValue.get().toString());

         attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_LASTNAME));
         person.setLastName(attValue == null ? null : attValue.get().toString());

         attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_EMAIL));
         person.setEmailAdress(attValue == null ? null : attValue.get().toString());

         attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_ACCOUNTNAME));
         person.setAccountName(attValue == null ? null : attValue.get().toString());

         attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_COUNTRY));
         person.setCountry(attValue == null ? null : attValue.get().toString());

         attValue = attributes.get(AppConfig.getProperty(LDAP_ATTRIBUTE_SID));
         if (attValue != null) {
            Object binary = attributes.get(AppConfig.getProperty(LDSDaoImpl.LDAP_ATTRIBUTE_SID)).get();
            person.setSid(LdapUtils.convertBinarySidToString((byte[]) binary));
         }
         else {
            person.setSid(null);
         }

         return person;
      }
   }

}
